﻿
using PoemGame.ApplicationService;
using PoemGame.ComputerAnswer.Shared;
using PoemGame.Domain.GameAggregate;
using PoemGame.Domain.PlayerAggregate;
using PoemGame.Domain.Services;
using PoemGame.WebDemoApplication.DTOs;

namespace PoemGame.WebDemoApplication
{
    public class PoemGameWebDemoApplication:IPoemGameWebDemoApplication
    {
        private readonly IGameFactory _factory;
        private readonly IGameRepository _gameRepository;
        private readonly IPlayerRepository _playerRepository;
        private readonly IDomainServiceFactory<ICheckAnswerService> _checkAnswerServiceFactory;
        private readonly IComputerAnswerFactory _computerAnswerFactory;
        public PoemGameWebDemoApplication(IGameFactory factory,
            IGameRepository gameRepository,
            IPlayerRepository playerRepository,
            IDomainServiceFactory<ICheckAnswerService> checkAnswerServiceFactory,
            IComputerAnswerFactory computerAnswerFactory
            )
        {
            _factory = factory;
            _gameRepository = gameRepository;
            _playerRepository = playerRepository;
            _checkAnswerServiceFactory = checkAnswerServiceFactory;
            _computerAnswerFactory = computerAnswerFactory;
        }
        public async Task<CreateGameResult> CreateGame(CreateGameInputDto createGameInput)
        {
            CreateGameResult createGameResult = new CreateGameResult();
            var playerme = await AddPlayer(createGameInput.UserName);
            var playercomputer = await AddPlayer("计算机");
            var res = await _factory.CreateGame(playerme, new GameType(createGameInput.GameType,createGameInput.GameSubType), PlayType.Inturn, "游戏" + createGameInput.GameType + " " + DateTime.Now + " " + createGameInput.GameCondition, createGameInput.GameCondition);
            var game = res.CreatedGame;

            if (res.IsSuccess)
            {
                game.PlayerJoinGame(playercomputer);
                game.Start();
                await _gameRepository.AddAsync(game);

                var answer = ComputerAnswer("", createGameInput.GameType, createGameInput.GameCondition);

                var resplay = await PlayAsync(game.Id, answer,"计算机");

                createGameResult.Success = true;
                createGameResult.GameId=game.Id;
                createGameResult.ComputerAnswer = answer;
                createGameResult.Message = resplay.Message;
            }
            else
            {
                createGameResult.Success = false;
                createGameResult.GameId = Guid.Empty;
                createGameResult.ComputerAnswer = "";
                createGameResult.Message = res.Message;
            }
            return createGameResult;
        }

        public async Task<PlayResult> Play(PlayInputDto playInput)
        {
            var game = await _gameRepository.GetAsync(playInput.GameId);
            if (game == null) return new PlayResult { Success = false, Message = "游戏不存在" };
            var res=await PlayAsync(playInput.GameId,playInput.Answer,playInput.UserName);
            if (!res.IsSuccess)
            {
                return new PlayResult { Success = false, Message = res.Message };
            }
            var answer = ComputerAnswer(playInput.Answer, game.GameType.MainType, game.GameCondition);
            var compres = await PlayAsync(playInput.GameId, answer, "计算机");
            if (!compres.IsSuccess)
            {
                return new PlayResult { Success = false, Message = res.Message };
            }

            return new PlayResult
            {
                Success = true, ComputerAnswer = answer, GameId = playInput.GameId,
                IsGameDone = (game.Status == GameStatus.Done || game.Status == GameStatus.DoneWithoutWinner),
                 Message=compres.Message
            };

        }

        private async Task<GamePlayResult> PlayAsync(Guid gameId, string answer,string username)
        {
            var inplayer = await _playerRepository.GetPlayerByUserNameAsync(username);
            if (inplayer==null)
            {
                return new GamePlayResult
                {
                    FaultReason = EnumGamePlayFaultReason.PlayerNotInGame,
                    IsAnswerCorrect = false,
                    IsGameDone = false,
                    IsSuccess = false
                };
            }

            var game = await _gameRepository.GetAsync(gameId);
            var playcurr = game.GetCurrentPlayer();

            if (inplayer.Id != playcurr.PlayerId)
            {
                return new GamePlayResult
                {
                    FaultReason = EnumGamePlayFaultReason.PlayerNotInGame,
                    IsAnswerCorrect = false,
                    IsGameDone = false,
                    IsSuccess = false
                };
            }

            var player = await _playerRepository.GetPlayerByIdAsync(playcurr.PlayerId);
            var isproperty = await game.Play(player, answer, _checkAnswerServiceFactory);

            var res = new GamePlayResult
            {
                IsSuccess = true,
                IsGameDone =false,
                IsAnswerCorrect =isproperty
            };
            if (isproperty)
            {
                res.IsGameDone = false;
                res.Message = player.UserName + "回答正确";
                playcurr.PlayerStatus = PlayerGameStatus.Waiting;
            }
            else
            {
                playcurr.PlayerStatus = PlayerGameStatus.Out;
                res.Message = player.UserName + "出局";
            }
            var activateplayers = game.GetWaitingPlayers();
            if (activateplayers.Count == 1 && isproperty)
            {
                var activateplayer = await _playerRepository.GetPlayerByIdAsync(activateplayers[0].PlayerId);
                res.Message += $"游戏结束,{activateplayer.UserName}获胜";
                game.GameOver(activateplayer);
                res.IsGameDone = true;
            }
            else if (activateplayers.Count == 0)
            {
                //游戏结束，没有赢家
                res.Message += $"游戏结束,没有赢家";
                game.GameOver();
                res.IsGameDone = true;
            }
            else
            {
                var nextplayer = game.GetNextPlayer(player.Id);
                game.SetPlayerInturn(nextplayer.PlayerId);

                var nplayer = await _playerRepository.GetPlayerByIdAsync(nextplayer.PlayerId);
                res.Message += $"轮到{nplayer.UserName}回答问题";
            }

            await _gameRepository.UpdateAsync(game);
            return res;
        }

        private async Task<Player> AddPlayer(string playerName)
        {
            var player = await _playerRepository.GetPlayerByUserNameAsync(playerName);
            if (player == null)
            {
                player = new Player(Guid.NewGuid(), playerName, playerName, 0);
                await _playerRepository.AddAsync(player);
            }

            return player;
        }

        private string ComputerAnswer(string lastanswer, string gametype, string gamecontext)
        {
            var answerservice = _computerAnswerFactory.Create(gametype);
            return answerservice.Answer(gamecontext, lastanswer);
        }
    }
}
